﻿using IM.Easy.Core.Extensions;
using IM.Easy.Core.Security;
using IM.Easy.Core.Services;
using IM.Easy.Core.Utils;
using IM.Easy.CoreServices.IServices;
using IM.Easy.Entity.System;
using IM.Easy.Infrastructure.Constants;
using IM.Easy.Infrastructure.Query;
using IM.Easy.SystemServices.Dtos.User;
using IM.Easy.SystemServices.IServices;
using Mapster;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IM.Easy.SystemServices.Services
{
    public class UserService : AppServices<SysUser>, IUserService
    {
        private readonly IParamsService _paramsService;
        public UserService(ISqlSugarClient db, IParamsService paramsService) : base(db)
        {
            _paramsService = paramsService;
        }
        public PageResponse<SysUser> GetList(UserQueryDto query, params long[] deptId)
        {
            if (deptId != null)
                deptId = deptId.Distinct().ToArray();  //这里用内连需要做去重处理
            var queryable = Db.Queryable<SysUser>();
            var exp = Expressionable.Create<SysUser>();
            exp = exp.AndIF(!string.IsNullOrEmpty(query.NickName), u => u.NickName.Contains(query.NickName))
                     .AndIF(!string.IsNullOrEmpty(query.Mobile), u => u.Mobile.Contains(query.Mobile))
                     .AndIF(!string.IsNullOrEmpty(query.UserName), u => u.UserName.Contains(query.UserName))
                     .AndIF(query.DeptId == default, u => u.DeptId == query.DeptId);

            var users = queryable
                        .InnerJoinIF(deptId != default, Db.Reportable(deptId).ToQueryable<long>(), (u, d) => u.DeptId == d.ColumnName)
                        .LeftJoin<SysDepartment>((u, d, sd) => u.DeptId == sd.Id)
                        .Where(exp.ToExpression())
                        .Select((u, d) => u)
                        .Includes(s => s.Department)
                        .Includes(s => s.Post.ToList(it => new SysPost { Id = it.Id, Name = it.Name }))
                        .ToPageList(query);

            return users;
        }

        /// <summary>
        /// 添加系统用户
        /// </summary>
        /// <param name="userDto"></param>
        /// <returns></returns>
        public UserResponseDto Create(UserCreateDto userDto)
        {
            var user = userDto.Adapt<SysUser>();
            if (IsDuplicateUserName(user.UserName)) ExceptionUtils.ThrowBusinessException($"用户名【{userDto.UserName}】重复");
            var password = GetInitPassword();
            user.Password = Sha256Hash.ComputeHash(password);
            user.IsLocked = false;

            //创建时默认为启用状态
            user.IsActive = true;
            user.Roles = userDto.RoleIds.Select(s => new SysRole { Id = s }).ToList();

            user = Context.InsertNav(user).Include(s => s.Roles).ExecuteReturnEntity();
            return user.Adapt<UserResponseDto>();
        }

        /// <summary>
        /// 通过名称判断用户是否存在
        /// </summary>
        /// <param name="userName"></param>
        /// <returns></returns>
        public bool IsDuplicateUserName(long userId, string userName)
        {
            return base.IsAny(s => s.Id != userId && s.UserName == userName);
        }

        /// <summary>
        /// 通过名称判断用户是否存在-----新增时做判断
        /// </summary>
        /// <param name="userName"></param>
        /// <returns></returns>
        public bool IsDuplicateUserName(string userName)
        {
            return base.IsAny(s => s.UserName == userName);
        }

        /// <summary>
        /// 检查是否为重复电话号
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="mobile"></param>
        /// <returns></returns>
        public bool IsDuplicateMobile(long userId, string mobile)
        {
            return base.IsAny(s => s.Id != userId && s.Mobile == mobile);
        }

        /// <summary>
        /// 传入铭文密码，初始化密码
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public bool InitPassword(long userId, string password)
        {
            var user = GetById(userId);
            if (string.IsNullOrEmpty(password)) ExceptionUtils.ThrowBusinessException("密码不能为空");
            user.Password = Sha256Hash.ComputeHash(password);
            var result = Db.Updateable(user)
                        .UpdateColumns(s => s.Password)
                        .ExecuteCommandHasChange();
            return result;
        }

        /// <summary>
        /// 获取初始化密码---铭文密码
        /// </summary>
        /// <returns></returns>
        public string GetInitPassword()
        {
            var password = _paramsService.GetValue(ParamsConstant.InitPassword);
            if (string.IsNullOrWhiteSpace(password)) ExceptionUtils.ThrowBusinessException($"系统参数:{ParamsConstant.InitPassword}，配置异常");
            return password;
        }

        /// <summary>
        /// 获取用户信息
        /// </summary>
        /// <returns></returns>
        public UserResponseDto GetUser(long id)
        {
            var user = Context.Queryable<SysUser>()
                    .Includes(s => s.Roles)
                    .First(s => s.Id == id);
            return user.Adapt<UserResponseDto>();
        }

        /// <summary>
        /// 删除用户
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public bool Delete(params long[] ids)
        {
            var result = Db.DeleteNav<SysUser>(s => ids.Contains(s.Id))
                  .Include(s => s.Roles, new DeleteNavOptions()
                  {
                      ManyToManyIsDeleteA = true
                  })
                  .ExecuteCommand();

            return result;
        }

        /// <summary>
        /// 修改用户信息
        /// </summary>
        /// <param name="userDto"></param>
        /// <returns></returns>
        public bool Update(UserCreateDto userDto)
        {
            var user = Db.Queryable<SysUser>().InSingle(userDto.Id);
            user.Roles = userDto.RoleIds.Select(s => new SysRole { Id = s }).ToList();
            user = userDto.Adapt(user);
            var result = Context.UpdateNav(user)
                  .Include(s => s.Roles, new UpdateNavOptions { ManyToManyIsUpdateA = true })
                  .ExecuteCommand();
            return result;
        }

        /// <summary>
        /// 禁用用户
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public bool Disable(long userId)
        {
            var user = GetById(userId);
            if (!user.IsActive) ExceptionUtils.ThrowBusinessException("操作失败：已经处于禁用状态");
            return base.Update(s => s.IsActive == false, s => s.Id == user.Id);
        }

        /// <summary>
        /// 启用用户
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public bool Enable(long userId)
        {
            var user = GetById(userId);
            if (user.IsActive) ExceptionUtils.ThrowBusinessException("操作失败：已经处于启用状态");
            return base.Update(s => s.IsActive == true, s => s.Id == user.Id);
        }
    }
}
